﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using PSE.Deployment.Engine;
using PSE.Deployment.Engine.Interfaces;
using PSE.Deployment.SetupBase;
using PSE.Deployment.SetupBase.Configuration;
using PSE.Deployment.Util;
using Sinacor.Deployment.Setup.DataAccess;
using Sinacor.Deployment.Setup.Main;
using Sinacor.Deployment.Setup.UI;
using Sinacor.Deployment.Setup.Wizard.Steps;

namespace Sinacor.Deployment.Setup.Wizard
{
    public class WizardGroup : BaseStepGroup
    {
        private Steps.SinacorComponents _sinacorComponents;
        private Steps.InstallationPath _installationPath;
        private Steps.DataBaseConnection _dataBaseConnection;
        private Steps.DataBaseCompany _dataBaseCompany;
        private Steps.ServiceCompany _serviceCompany;
        private Steps.MSMQ _msmq;

        public WizardGroup(IStepGroup parent)
            : base(parent)
        {
            this.Id = "WizardGroup";

            this.ErrorBehavior = PSE.Deployment.Engine.Enums.StepErrorBehavior.CancelParent;
            this.CancelBehavior = PSE.Deployment.Engine.Enums.StepGroupCancelBehavior.CancelParent;
            this.NavigationBehavior = PSE.Deployment.Engine.Enums.StepNavigationBehavior.NextCancel;

            _sinacorComponents = new SinacorComponents(this);
            _sinacorComponents.ExecutionFinished += new EventHandler<PSE.Deployment.Engine.CustomEventArgs.ExecutionFinishedEventArgs>(_sinacorComponents_ExecutionFinished);

            if (!SetupMainFactory.GetInstance<SinacorMain>().Parameter.IsInstalled)
            {
                this.Steps.Add(new Steps.Introduction(this));
                this.Steps.Add(new Steps.License(this));
            }

            this.Steps.Add(new Steps.Prerequisite(this));
            this.Steps.Add(_sinacorComponents);

            _installationPath = new Steps.InstallationPath(this);
            _dataBaseConnection = new Steps.DataBaseConnection(this);
            _dataBaseCompany = new Steps.DataBaseCompany(this);
            _serviceCompany = new Steps.ServiceCompany(this);
            _msmq = new Steps.MSMQ(this);

            _dataBaseConnection.ExecutionFinished += new EventHandler<PSE.Deployment.Engine.CustomEventArgs.ExecutionFinishedEventArgs>(_dataBaseConnection_ExecutionFinished);
        }

        private void _dataBaseConnection_ExecutionFinished(object sender, PSE.Deployment.Engine.CustomEventArgs.ExecutionFinishedEventArgs e)
        {
            RemoveCustomizedStepsAfterDataBaseConnection();

            if (e.NavigationAction == PSE.Deployment.Engine.Enums.StepNavigationAction.Next)
            {
                List<Group> groups = SetupMainFactory.GetInstance<SinacorMain>().Configuration.SystemInfo.Groups.SelectDeep(g => g.SubGroups).ToList();
                Group dataBaseGroup = groups.Find(g => g.Id == "Database");
                Group serviceGroup = groups.Find(g => g.Id == "ServiceLayer");
                Group msmqGroup = groups.Find(g => g.Id == "MSMQ");

                if (dataBaseGroup != null && (dataBaseGroup.Install == null || dataBaseGroup.Install.GetValueOrDefault()))
                {
                    this.Steps.Add(_dataBaseCompany);
                }

                if (serviceGroup != null && (serviceGroup.Install == null || serviceGroup.Install.GetValueOrDefault()) && !CheckAllCompaniesCompatibility())
                {
                    this.Steps.Add(_serviceCompany);
                }

                if (msmqGroup != null && (msmqGroup.Install == null || msmqGroup.Install.GetValueOrDefault()))
                {
                    this.Steps.Add(_msmq);
                }
            }
        }

        private void RemoveCustomizedSteps()
        {
            this.Steps.Remove(_installationPath);
            this.Steps.Remove(_dataBaseConnection);
            this.Steps.Remove(_dataBaseCompany);
            this.Steps.Remove(_serviceCompany);
            this.Steps.Remove(_msmq);
        }

        private void RemoveCustomizedStepsAfterDataBaseConnection()
        {
            this.Steps.Remove(_dataBaseCompany);
            this.Steps.Remove(_serviceCompany);
            this.Steps.Remove(_msmq);
        }

        private void _sinacorComponents_ExecutionFinished(object sender, PSE.Deployment.Engine.CustomEventArgs.ExecutionFinishedEventArgs e)
        {
            RemoveCustomizedSteps();

            List<Group> groups = SetupMainFactory.GetInstance<SinacorMain>().Configuration.SystemInfo.Groups.SelectDeep(g => g.SubGroups).ToList();
            Group dataBaseGroup = groups.Find(g => g.Id == "Database");
            Group serviceGroup = groups.Find(g => g.Id == "ServiceLayer");
            Group userInterfaceGroup = groups.Find(g => g.Id == "InterfaceLayer");
            Group processManagerGroup = groups.Find(g => g.Id == "ProcessManager");
            Group msmqGroup = groups.Find(g => g.Id == "MSMQ");

            if (!SetupMainFactory.GetInstance<SinacorMain>().Parameter.IsInstalled)
            {
                if (serviceGroup != null && userInterfaceGroup != null && processManagerGroup != null &&
                    ((serviceGroup.Install == null || serviceGroup.Install.GetValueOrDefault()) ||
                    (userInterfaceGroup.Install == null || userInterfaceGroup.Install.GetValueOrDefault()) ||
                    (processManagerGroup.Install == null || processManagerGroup.Install.GetValueOrDefault())))
                {
                    this.Steps.Add(_installationPath);
                }
            }
            //else
            //{
            //    if (serviceGroup != null && userInterfaceGroup != null && processManagerGroup != null &&
            //        (((serviceGroup.Install == null || serviceGroup.Install.GetValueOrDefault()) && !serviceGroup.Installed) ||
            //        ((userInterfaceGroup.Install == null || userInterfaceGroup.Install.GetValueOrDefault()) && !userInterfaceGroup.Installed) ||
            //        ((processManagerGroup.Install == null || processManagerGroup.Install.GetValueOrDefault()) && !processManagerGroup.Installed)))
            //    {
            //        this.Steps.Add(_installationPath);
            //    }
            //}

            if ((serviceGroup != null && (serviceGroup.Install == null || serviceGroup.Install.GetValueOrDefault())) ||
                (dataBaseGroup != null && (dataBaseGroup.Install == null || dataBaseGroup.Install.GetValueOrDefault())) ||
                (processManagerGroup != null && (processManagerGroup.Install == null || processManagerGroup.Install.GetValueOrDefault())))
            {
                this.Steps.Add(_dataBaseConnection);
            }

            if (msmqGroup != null && (msmqGroup.Install == null || msmqGroup.Install.GetValueOrDefault()))
            {
                this.Steps.Add(_msmq);
            }
        }

        private bool CheckAllCompaniesCompatibility()
        {
            bool checkCompaniesCompatibility = true;

            if (String.IsNullOrEmpty(SetupMainFactory.GetInstance<SinacorMain>().Parameter.DataBase.ConnectionInfo.User) || String.IsNullOrEmpty(SetupMainFactory.GetInstance<SinacorMain>().Parameter.DataBase.ConnectionInfo.Password) || String.IsNullOrEmpty(SetupMainFactory.GetInstance<SinacorMain>().Parameter.DataBase.ConnectionInfo.TNSName))
                return checkCompaniesCompatibility;

            foreach (Sinacor.Deployment.Setup.Configuration.VersionInfo versionInfo in SetupMainFactory.GetInstance<SinacorMain>().Configuration.DataBase.Versions)
            {
                using (OracleDataBase db = new OracleDataBase(SetupMainFactory.GetInstance<SinacorMain>().Parameter.DataBase.ConnectionInfo.User, EncryptDecrypt.Decrypt(SetupMainFactory.GetInstance<SinacorMain>().Parameter.DataBase.ConnectionInfo.Password), SetupMainFactory.GetInstance<SinacorMain>().Parameter.DataBase.ConnectionInfo.TNSName, SetupMainFactory.GetInstance<SinacorMain>().Parameter.DataBase.ConnectionInfo.IsEncrypted))
                {
                    StringBuilder sqlCommand = new StringBuilder();

                    sqlCommand.Append("SELECT E.CD_EMPRESA, E.NM_EMPRESA, E.CD_USUA_ORAC, I.VS_SIST_INST FROM TGEEMPR E LEFT JOIN TGESINST I ON E.CD_EMPRESA = I.CD_EMPRESA and I.CD_SISTEMA = :CodSistema");
                    List<DataBaseParameter> dataBaseParameter = new List<DataBaseParameter>();
                    DataBaseParameter paramSistema = new DataBaseParameter("CodSistema", versionInfo.Module.Id.ToUpper());
                    dataBaseParameter.Add(paramSistema);

                    CompanyVersion version = new CompanyVersion();
                    version.SetupVersions = SetupMainFactory.GetInstance<SinacorMain>().Configuration.DataBase.Versions.Find(v => v.Module.Id == versionInfo.Module.Id).Versions;

                    using (IDataReader dr = db.ExecuteReader(sqlCommand.ToString(), dataBaseParameter))
                    {
                        while (dr.Read())
                        {
                            if (!version.SetupVersions.Contains(dr[3].ToString()))
                                checkCompaniesCompatibility = false;

                            if (!checkCompaniesCompatibility)
                                break;
                        }
                    }
                }

                if (!checkCompaniesCompatibility)
                    break;
            }

            return checkCompaniesCompatibility;
        }
    }
}
